import numpy as np
import matplotlib.pyplot as plt


def regressao_linear(x,y):

    n = len(x)

    #somas
    sumX = sum(x)
    sumY = sum(y)

    sumX2 = sum(x**2)
    sumY2 = sum(y**2)
    sumXY = sum(x * y)

    #m , b, r2
    m = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX**2)
    b = (sumX2 * sumY - sumX * sumXY) / (n * sumX2 - sumX**2)
    r2 = (n * sumXY - sumX * sumY)**2 / ((n * sumX2 - sumX**2) * (n * sumY2 - sumY**2))

    #incertezas
    dM = abs(m) * np.sqrt(((1 / r2) - 1) / (n - 2))
    dB = dM * np.sqrt(sumX2 / n)

    return m, b, r2, dM, dB




def grafico(L,X):
    plt.plot(L, X, 'ro')
    plt.xlabel('distância luz-alvo (cm)')
    plt.ylabel('distância máximos luminosos (cm)')
    plt.title('Regressão Linear')
    plt.grid()
    plt.show()


def grafico_reta(m, b, L, X):
    plt.plot(L, X, 'ro')
    plt.plot(L, m*L + b)
    plt.xlabel('distância luz-alvo (cm)')
    plt.ylabel('distância máximos luminosos (cm)')
    plt.title('Regressão Linear')
    plt.grid()
    plt.show()



def main():	

    L = np.array([222.0, 207.5, 194.0, 171.5, 153.0, 133.0, 113.0, 92.0]) #(X)
    X = np.array([2.3, 2.2, 2.0, 1.8, 1.6, 1.4, 1.2, 1.0]) #(Y)

    #a - dados experimentais num gráfico
    grafico(L,X)

    #b
    m, b, r2, dm, db = regressao_linear(L, X)
    print(f"m = {m:.8f}")
    print(f"b = {b:.8f}")
    print(f"r² = {r2:.8f}")
    print(f"Δm = {dm:.8f}")
    print(f"Δb = {db:.8f}")

    #c  reta 𝑦 = 𝑚𝑥 + 𝑏 no gráfico.
    grafico_reta(m, b, L, X)

    #d Interpolação: Encontre o valor de 𝑋, quando 𝐿 = 165.0 cm
    newL = 165.0
    newX = m * newL + b
    print(f"Valor Interpolado de X = {newX:.1f} cm")


    #e Afaste da reta encontrada um dos valores medidos de 𝑦. 
    L_mod = L.copy()
    L_mod[-1] += 5
    grafico_reta(m, b, L_mod, X)
    m, b, r2, dm, db = regressao_linear(L_mod, X)
    print(f"m = {m:.8f}")
    print(f"b = {b:.8f}")
    print(f"r² = {r2:.8f}")
    print(f"Δm = {dm:.8f}")
    print(f"Δb = {db:.8f}")



if __name__ == "__main__":
    main()